# 用于收集汇总所有设备的警告信息
module Aio::Warning
  class WarningSummarize

    # 按结构保存警告信息
    # summary = { :serious => 
    # 							{ :crc => 
    # 									{ device_name => 
    # 											{ :klass =>device_klass] ,
    #                         :detail => device_klass.warning }} }
    attr_reader :summary

    # 设备的警告信息
    # device_warning = { device_name => device_warning_klass }
    attr_reader :device_warning

    def initialize(device_manager)
      @device_manager = device_manager
      @description = Description.new(device_manager.module_manager)
      clear
    end

    # 通过case获取描述模块的实例
    def get_desc(sym)
      @description.get_desc(sym)
    end

    def inspect
      "#<Aio::Warning::WarningSummarize @summary, @device_warning>"
    end

    # 整理警告信息
    # 改变结构变成 
    def tidy_warning
      # 清除原先 summary
      clear

      devices.each_pair do |device, klass|
        warning_klass = klass.warning_klass
        @device_warning[device] = klass.warning_klass

        # 当有严重警告的时候
        if warning_klass.has_warning_serious?
          append_issue(warning_klass.warning_info_serious, :serious, device, klass)
        end

        # 当有一般信息的时候
        if warning_klass.has_warning_ordinary?
          append_issue(warning_klass.warning_info_ordinary, :ordinary, device, klass)
        end

        # 当有比较误差信息的时候
        # NOTE 这个比较暂时去掉
        if warning_klass.has_warning_compare?
        #  append_issue(warning_klass.warning_info_compare, :compare, device, klass)

          append_issue_compare(warning_klass.warning_info_compare, device, klass)
        end
      end

      @summary
    end

    # 增加警告信息
    def append_issue(warning_info, level, device, klass)
      warning_info.each_pair do |issue, detail|
        # 如果没有, 则加入Hash
        unless summary[level].has_key?(issue)
          summary[level][issue] = {}
        end

        summary[level][issue][device] = { :klass => klass, :detail => detail }
      end
    end

    # 针对compare添加警告信息
    # 为了跟其他种类的警告信息一致，重复两次:compare
    def append_issue_compare(warning_info, device, klass)
      summary[:compare][:compare] = {}
      summary[:compare][:compare][device] = { 
        klass: klass,
        detail: warning_info
      }
    end

    # 严重警告条数
    def serious_number
      number(summary[:serious])
    end

    # 一般警告信息条数
    def ordinary_number
      number(summary[:ordinary])
    end

    # 比较差异警告条数
    def compare_number
      number(summary[:compare])
    end

    # 全部警告条数
    def total_number
      serious_number + ordinary_number + compare_number
    end

    # 统计警告条目数
    def number(hash)
      num = 0
      hash.each_value do |v|
        num += v.size
      end

      return num
    end

    def has_serious?
      serious_number > 0 ? true : false
    end

    def has_ordinary?
      ordinary_number > 0 ? true : false
    end

    def has_compare?
      compare_number > 0 ? true : false
    end

    # 按照权重,对 device_warning 排序
    def device_warning_sort
      arr = device_warning.to_a
      arr.sort! do |x, y|
        x1 = x[1]
        y1 = y[1]
        x_wgt = (x1.serious_number*5) + (x1.ordinary_number) + (x1.compare_number*3)
        y_wgt = (y1.serious_number*5) + (y1.ordinary_number) + (y1.compare_number*3)
        y_wgt <=> x_wgt
      end

      return arr
    end

    # 按照设备分类取到的严重警告数
    def device_serious_sort
      st = []
      @device_warning.each_pair do |name, klass|
        st << [name, klass.serious_number]
      end

      st.sort! do |x, y|
        y[1] <=> x[1]
      end

      st.delete_if do |x|
        x[0].empty? or x[1] == 0
      end
    end

    # 按照设备分类取到的一般警告数
    def device_ordinary_sort
      st = []
      @device_warning.each_pair do |name, klass|
        st << [name, klass.ordinary_number]
      end

      st.sort! do |x, y|
        y[1] <=> x[1]
      end

      st.delete_if do |x|
        x[0].empty? or x[1] == 0
      end
    end

    # 发生频率高的问题
    def problem_frequency
      tmp = []
      summary.each_value do |info|
        info.each_pair do |prb, dvs|
          tmp << [prb, dvs.size]
        end
      end

      # 反向排序
      tmp.sort { |x, y| x[1] <=> y[1] }.reverse
    end

    # 取得严重信息的描述列表
    # 返回结构: 
    # 	:crc => { :description => CRC描述类,
    #							:devices => [[dev1, klass1], ...] }
    def serious_description
      res = {}
      serious_info.each_pair do |prb, dvs_info|
        res[prb] = { :description => @descripion.get(prb) }
        tmp = []
        dvs_info.each_pair do |device_name, info|
          tmp << [device_name, info[:klass]]
        end
        res[prb][:devices] = tmp
      end

      return res
    end

    # 严重信息
    def serious_info
      summary[:serious]
    end

    def ordinary_info
      summary[:ordinary]
    end

    def compare_info
      summary[:compare]
    end

    private

    # 清零变量
    def clear
      clear_summary
      clear_device_warning
    end

    def clear_summary
      @summary = {
        :serious  => {},
        :ordinary => {},
        :compare  => {}
      }
    end

    def clear_device_warning
      @device_warning = {}
    end

    # 方便使用
    def device_manager
      @device_manager
    end

    # 方便使用 devices
    def devices
      device_manager.devices
    end

  end
end
